package com.spring.boot.reflect;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;

/**反射工具类 hd 2019-06-29
 * 根据属性名称与属性设置的内容
 */
public class BeanOperate {

    private Object obj;  //操作对象
    private String pro;  //操作属性
    private Object value;  //数据内容
    private Field field; //操作的属性
    private String fieldName;//保存成员变量名称
    private Object currentObj;//操作属性的对象
    /**
     * 本类只要一些基本信息
     * @param obj 操作的对象
     * @param pro 属性名称
     * @param val 要操作的内容
     */
    public BeanOperate(Object obj , String pro , Object val) throws Exception{
        this.obj = obj;
        this.pro = pro;
        this.value = val;
        handleString();
        setFileValue();
    }

    //处理字符串，从中区分要操作的属性和对象
    private void handleString() throws Exception{
        //按.拆分
        String[] result = this.pro.split("\\.");
        //设置当前一个操作的对象
        this.currentObj = this.obj;
        try {
            //如果只有一个.
            if (result.length == 2){
                this.field = this.currentObj.getClass().getDeclaredField(result[1]);
                this.fieldName = result [1];
            }else {
                for (int i = 1; i < result.length; i++) {
                    //找到get方法
                    Method met = this.currentObj.getClass().getMethod("get" + StringUtils.init(result[i]));
                    this.field = currentObj.getClass().getDeclaredField(result[i]);
                    this.fieldName = result [i];
                    if (i < result.length-1){//后面还有对象
                        currentObj=met.invoke(currentObj);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 设置指定属性的内容，用set方法
     */
    private void setFileValue() throws Exception{
        try {
            //找到set方法
            Method setMet = this.currentObj.getClass().getDeclaredMethod("set"+StringUtils.init(this.fieldName),this.field.getType());

            //获取属性的名称
            String type = this.field.getType().getSimpleName();

            //保存处理后的数据
            String valueType = this.value.getClass().getSimpleName();
            String val = null;
            //如果传入的参数类型是string则进入转换
            if ("string".equalsIgnoreCase(valueType)) {
                val = this .value.toString();
                //判断传入的值是什么类型
                if ("int".equalsIgnoreCase(type) || "Integer".equalsIgnoreCase(type)) {
                    if (val.matches("\\d+")) {
                        setMet.invoke(currentObj, Integer.parseInt(val));
                    }
                } else if ("double".equalsIgnoreCase(type) || "Double".equalsIgnoreCase(type)) {
                    if (val.matches("\\d+(\\.\\d+)")) {
                        setMet.invoke(currentObj, Double.parseDouble(val));
                    }
                } else if ("date".equalsIgnoreCase(type)) {
                    if (val.matches("\\d{4}-\\d{2}-\\d{2}")) {
                        setMet.invoke(currentObj, new SimpleDateFormat("yyyy-MM-dd").parse(val));
                    }
                } else if ("string".equalsIgnoreCase(type)) {
                    setMet.invoke(currentObj, val);
                }
            }else {
                //传入的是数组,将object变成数组
                String vals[] = (String[])this.value;
                this.field.setAccessible(true);
                if ("string[]".equalsIgnoreCase(type)) {
//                    setMet.invoke(currentObj, vals);不能设置
                    //只能用set方法强行设置
                    this.field.set(this.currentObj,vals);
                }else if ("Integer[]".equalsIgnoreCase(type)||"int[]".equalsIgnoreCase(type)) {
                    //定义数组把值放入
                    Integer data[] = new Integer[vals.length];
                    for (int i = 0; i < vals.length; i++) {
                        data[i] = Integer.parseInt(vals[i]);
                    }
                    this.field.set(this.currentObj,data);
                }else if ("Double[]".equalsIgnoreCase(type)) {
                    Double data[] = new Double[vals.length];
                    for (int i = 0; i < vals.length; i++) {
                        data[i] = Double.parseDouble(vals[i]);
                    }
                    this.field.set(this.currentObj,data);
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public Field getField() {
        return field;
    }

    public Object getCurrentObj() {
        return currentObj;
    }
}
